using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Manazra.Models;
using Manazra.Models.Repository;
using Manazra.Helpers;
using Manazra.Controllers.Filters;

namespace Manazra.Controllers
{
    //viewmodel class for article data
    public class ArticleViewModel
    {
        //properties
        public Article Article { get; private set; }
        public String Referrer { get; private set; }

        //categories list
        public SelectList Categories { get; set; }

        //constructor
        public ArticleViewModel(Article article)
        {
            Article = article;
        }
        public void SetReferrer(String referrer)
        {
            Referrer = referrer;
        }
    }

    [BasePreControllerActionFilter]
    public class ArticlesController : Controller
    {
        //articles repository
        private ArticleRepository articleRep = new ArticleRepository();
        //blog repository
        private BlogRepository blogRep = new BlogRepository();

        private const int listingPageSize = 10;

        //get all recent articles
        public ActionResult Index(int? page)
        {
            var articles = articleRep.GetRecent();
            //apply paging
            var paginatedArticles = new PaginatedList<Article>(articles, page ?? 0, listingPageSize);
            //show view
            return View(paginatedArticles);
        }

        //gets all popular articles
        public ActionResult Popular(int? page)
        {
            //get articles
            var articles = articleRep.GetPopular();
            //apply paging
            var paginatedArticles = new PaginatedList<Article>(articles, page ?? 0, listingPageSize);
            //show view
            return View("Index", paginatedArticles);
        }

        //gets the top few articles
        public JsonResult TopRanked(int count)
        {
            var articles = articleRep.TopRanked(count);
            return Json(articles);
        }

        //articles for categories
        public ActionResult Category(String id, int? page)
        {
            //get articles
            var articles = articleRep.GetByCategory(id.Replace('_', ' '));
            //apply paging
            var paginatedArticles = new PaginatedList<Article>(articles, page ?? 0, listingPageSize);
            //show view
            return View("CategoryIndex", paginatedArticles);
        }

        //articles for category by popularity
        public ActionResult CategoryAndPopular(string id, int? page)
        {
            //get articles
            var articles = articleRep.GetByCategoryAndPopular(id.Replace('_', ' '));
            //apply paging
            var paginatedArticles = new PaginatedList<Article>(articles, page ?? 0, listingPageSize);
            //show view
            return View("CategoryIndex", paginatedArticles);
        }

        //detail view on article
        public ActionResult Details(string id)
        {
            int intId = Int32.Parse(id.Split('_')[0]);
            Article article = articleRep.GetById(intId);
            if (article == null)
                return View("NotFound");
            else
            {
                //get authentication object from the view data
                UserAuth UserAuth = (UserAuth)ViewData["UserAuth"];
                //if anyone other than author is viewing the article - give it viewing potins
                if (!String.IsNullOrEmpty(UserAuth.UserName) && !article.IsAuthor(UserAuth.UserName))
                {
                    //award this article points for being viewed
                    articleRep.AddPoints(article);
                    articleRep.Save();
                }
                //show view
                return View(new ArticleViewModel(article));
            }
        }

        //edits an article
        [AuthorizeFBOK]
        public ActionResult Edit(int id)
        {
            Article article = articleRep.GetById(id);
            if (article == null)
                return View("NotFound");
            else
            {
                //get authentication object from the view data
                UserAuth UserAuth = (UserAuth)ViewData["UserAuth"];

                //make sure the author is trying to edit
                if (article.IsAuthor(UserAuth.UserName))
                {
                    //set article categories in view model
                    ArticleViewModel viewModel = new ArticleViewModel(article);
                    viewModel.Categories = new SelectList(articleRep.GetCategories().AsEnumerable(), "RecId", "Title", article.CategoryId);
                    return View(viewModel);
                }
                else
                    return View("InvalidOwner");
            }
        }

        //edit method for post requests
        [AcceptVerbs(HttpVerbs.Post), AuthorizeFBOK, ValidateInput(false)]
        public ActionResult Edit(int id, FormCollection formValues)
        {
            Article article = articleRep.GetById(id);
            if (article == null)
                return View("NotFound");
            else
            {
                //get authentication object from the view data
                UserAuth UserAuth = (UserAuth)ViewData["UserAuth"];

                //make sure the author is making changes
                if (article.IsAuthor(UserAuth.UserName))
                {
                    try
                    {
                        //set articles properties
                        article.Title = formValues["Title"];
                        article.Intro = formValues["Intro"];
                        article.CategoryId = Int32.Parse(formValues["Category"]);
                        article.UpdatedDate = DateTime.Now;

                        //save article segments
                        articleRep.SaveSegments(article, formValues);
                        //save changes
                        articleRep.Save();
                        //redirect to details page
                        return RedirectToAction("Details", new { id = article.RecId });
                    }
                    catch
                    {
                        //use model state to show errors
                        ModelState.AddRuleViolations(article.GetRuleViolations());
                        return View(new ArticleViewModel(article));
                    }
                }
                else
                    return View("InvalidOwner");
            }
        }

        //create a new article
        [AuthorizeFBOK]
        public ActionResult Create(String r)
        {
            Article article = new Article();
            //create article view model object
            ArticleViewModel viewModel = new ArticleViewModel(article);
            //specify who asked for the article to be created
            if (r != null)
                viewModel.SetReferrer(r);
            //list of categories
            viewModel.Categories = new SelectList(articleRep.GetCategories().AsEnumerable(), "RecId", "Title");
            //show view
            return View(viewModel);
        }

        //create method for post requests
        [AcceptVerbs(HttpVerbs.Post), AuthorizeFBOK, ValidateInput(false)]
        public ActionResult Create(Article article, FormCollection formValues)
        {
            try
            {
                //get authentication object from the view data
                UserAuth UserAuth = (UserAuth)ViewData["UserAuth"];

                //set articles properties                
                article.Author = UserAuth.UserName;
                article.CreatedDate = DateTime.Now;
                article.UpdatedDate = DateTime.Now;
                article.Title = formValues["Title"];
                article.Intro = formValues["Intro"];
                article.Category = articleRep.GetCategoryById(Int32.Parse(formValues["Category"]));

                //add new article
                articleRep.Add(article);

                //save article segments
                articleRep.SaveSegments(article, formValues);

                //check if this article belongs to a blog
                var referrer = formValues["r"];
                if (!String.IsNullOrEmpty(referrer))
                {
                    int blogId = Int32.Parse(referrer.Split('_')[1]) / 32;
                    //try getting this blog
                    Blog blog = blogRep.GetById(blogId);
                    if (blog != null)
                    {
                        //lets create a new blog article relation entry
                        BlogEntry blogEntry = new BlogEntry();
                        blogEntry.BlogId = blog.RecId;
                        //make connection
                        article.BlogEntries.Add(blogEntry);
                    }
                }

                //save changes
                articleRep.Save();

                //for facebook users we publish the new article news to their stream
                if (UserAuth.IsFacebookUser)
                {
                    //publish news for the new article on facebook
                    new FBPublisher().PublishNewArticleFeed(UserAuth, article);
                }

                //redirect to details page
                return RedirectToAction("Details", new { id = article.RecId + "_" + article.Title.Replace('_', ' ') });
            }
            catch
            {
                //use model state to show errors
                ModelState.AddRuleViolations(article.GetRuleViolations());
                //create article view model object
                ArticleViewModel viewModel = new ArticleViewModel(article);
                //specify who asked for the article to be created
                if (formValues["r"] != null)
                    viewModel.SetReferrer(formValues["r"]);
                //list of categories
                viewModel.Categories = new SelectList(articleRep.GetCategories().AsEnumerable(), "RecId", "Title", article.CategoryId);
                //show view
                return View(viewModel);
            }
        }

        //deletes an article
        [AuthorizeFBOK]
        public ActionResult Delete(int id)
        {
            Article article = articleRep.GetById(id);
            if (article == null)
                return View("NotFound");
            else
            {
                //get authentication object from the view data
                UserAuth UserAuth = (UserAuth)ViewData["UserAuth"];

                //make sure the author is trying to delete
                if (article.IsAuthor(UserAuth.UserName))
                    return View(new ArticleViewModel(article));
                else
                    return View("InvalidOwner");
            }
        }

        //post method for delete
        [AcceptVerbs(HttpVerbs.Post), AuthorizeFBOK]
        public ActionResult Delete(int id, FormCollection formValues)
        {
            Article article = articleRep.GetById(id);
            if (article == null)
                return View("NotFound");
            else
            {
                //get authentication object from the view data
                UserAuth UserAuth = (UserAuth)ViewData["UserAuth"];

                //make sure its the author
                if (article.IsAuthor(UserAuth.UserName))
                {
                    articleRep.Delete(article);
                    articleRep.Save();
                }
                else
                    return View("InvalidOwner");
            }

            //get new listing of articles
            return RedirectToAction("Index");
        }
    }
}